﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace EasyTrader.Order
{
    using PriceOrderList = List<EasyTrader.Order.OrderInfo>;
    public class OrderManager
    {
        public OrderManager()
        {
            InitTimer();
        }

        System.Timers.Timer timer = new System.Timers.Timer();
        private void InitTimer()
        {
            timer.Interval = 200;
            timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimerTick);
            timer.Enabled = true;
        }

        private void OnTimerTick(object sender, EventArgs e)
        {
            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    // 현재 수익을 계산해 준다.
                    double fixedProfit = 0;
                    double flowProfit = 0;
                    curTable.CalcProfit(ref fixedProfit, ref flowProfit, GlobalVar.CurClose);
                }
            }
        }

        public bool CanTakeAutoOrder(int a_CurTime)
        {
            int startTime = GlobalVar.TimeToInt(GlobalVar.OrderStartHour, GlobalVar.OrderStartMin);
            int endTime = GlobalVar.TimeToInt(GlobalVar.OrderEndHour, GlobalVar.OrderEndMin);
            if (a_CurTime >= startTime && a_CurTime <= endTime)
                return true;
            else
                return false;
        }

        public bool CanTakeAutoOrder(int a_CurTime, int a_OrderStartHour, int a_OrderStartMin, int a_OrderEndHour, int a_OrderEndMin)
        {
            int startTime = GlobalVar.TimeToInt(a_OrderStartHour, a_OrderStartMin);
            int endTime = GlobalVar.TimeToInt(a_OrderEndHour, a_OrderEndMin);
            if (a_CurTime >= startTime && a_CurTime <= endTime)
                return true;
            else
                return false;
        }

        private string SendPendingOrder(OrderTable a_Table, string a_OrderNum)
        {
            string orderNum = "";
            if (m_OrderDataSet == null || a_Table == null)
                return orderNum;
            if (a_Table.PendingOrder == true && a_Table.LiquidatingOrderNumber == a_OrderNum)
            {
                object a_Market = "1";
                object a_Account = a_Table.TableName;
                object a_ItemCode = GetCurFutureCode();
                object a_Amount = a_Table.PendingOrderAmount;
                object a_OrderPrice = a_Table.PendingOrderVal;
                object a_BuySell = a_Table.PendingOrderBuySell;
                object a_OrderType = GlobalVar.OrderType;
                object a_OrderCond = GlobalVar.OrderCond;
                orderNum = SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                a_Table.PendingOrder = false;
                string orderInfo = "청산주문후 펜딩 주문 정보 ->";
                orderInfo += "주문계좌 : " + a_Account + ", ";
                orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                orderInfo += "주문수량 : " + a_Amount.ToString();
                GlobalVar.WriteLog(orderInfo);
            }
            return orderNum;
        }
        // 청산후 신규 주문을 보낸다.
        public void LiquidAndOrder(int a_BuySell, int a_OrderAmount, double a_CurVal)
        {
            GlobalVar.DownloadLock = true;
            // 가장 먼저 청산 가능 수량이 있는지 조사한다.
            // 청산 가능 수량이 있으면 현재 주문 정보를 해당 계좌의 테이블에 저장해 둔다.
            // 그리고 청산 주문을 낸다. 해당 계좌의 테이블에 현재 청산 주문이 나갔음을 설정해 둔다.
            // 청산 주문이 완료 되면 원래 주문 정보를 가져와 본 주문을 넣어 준다.
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    DataRow lastRow = curTable.Rows[rowCount - 1];
                    int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                    string remainCode = lastRow["잔고구분코드"].ToString();
                    // 청산 가능 수량이 0보다 클 때
                    if (remainCode != "" && (remainCode == "1" || remainCode == "2") && liquidAmount > 0)
                    {
                        object a_Market = "1";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = m_FCode.GetData(0, 0);
                        object a_Amount = liquidAmount;
                        object a_OrderPrice = a_CurVal;
                        object a_OldBuySell;
                        object a_OrderType = 2;
                        object a_OrderCond = 0;
                        string orderNum = "";
                        // 매도 잔고가 남아 있는 상태임
                        if (remainCode == "1")
                        {
                            a_OldBuySell = GlobalVar.OrderBuy; // 매수 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            orderNum = SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            curTable.PendingOrderBuySell = a_BuySell;
                            curTable.PendingOrderVal = a_CurVal;
                            curTable.PendingOrderAmount = a_OrderAmount;
                            curTable.PendingOrder = true;
                            curTable.LiquidatingOrderNumber = orderNum;
                        }
                        else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                        {
                            // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                            a_OldBuySell = GlobalVar.OrderSell; // 매도 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            orderNum = SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            curTable.PendingOrderBuySell = a_BuySell;
                            curTable.PendingOrderVal = a_CurVal;
                            curTable.PendingOrderAmount = a_OrderAmount;
                            curTable.PendingOrder = true;
                            curTable.LiquidatingOrderNumber = orderNum;
                        }
                    }
                }
            }

            GlobalVar.DownloadLock = false;
        }

        // 청산후 신규 주문을 보낸다.
        public void SendAutoLiquidAndOrder(int a_BuySell, int a_OrderAmount, double a_CurVal)
        {
            GlobalVar.DownloadLock = true;
            // 가장 먼저 청산 가능 수량이 있는지 조사한다.
            // 청산 가능 수량이 있으면 현재 주문 정보를 해당 계좌의 테이블에 저장해 둔다.
            // 그리고 청산 주문을 낸다. 해당 계좌의 테이블에 현재 청산 주문이 나갔음을 설정해 둔다.
            // 청산 주문이 완료 되면 원래 주문 정보를 가져와 본 주문을 넣어 준다.
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    DataRow lastRow = curTable.Rows[rowCount - 1];
                    int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                    string remainCode = lastRow["잔고구분코드"].ToString();
                    // 청산 가능 수량이 0보다 클 때
                    if (remainCode != "" && (remainCode == "1" || remainCode == "2") && liquidAmount > 0)
                    {
                        object a_Market = "1";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = m_FCode.GetData(0, 0);
                        object a_Amount = liquidAmount;
                        object a_OrderPrice = a_CurVal;
                        object a_OldBuySell;
                        object a_OrderType = 2;
                        object a_OrderCond = 0;
                        string orderNum = "";
                        // 매도 잔고가 남아 있는 상태임
                        if (remainCode == "1")
                        {
                            a_OldBuySell = GlobalVar.OrderBuy; // 매수 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            orderNum = SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_OldBuySell, a_OrderType, a_OrderCond);
                            curTable.PendingOrderBuySell = a_BuySell;
                            curTable.PendingOrderVal = a_CurVal;
                            curTable.PendingOrderAmount = a_OrderAmount;
                            curTable.PendingOrder = true;
                            curTable.LiquidatingOrderNumber = orderNum;
                            string orderInfo = "자동 청산 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_OldBuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                        else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                        {
                            // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                            a_OldBuySell = GlobalVar.OrderSell; // 매도 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            orderNum = SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_OldBuySell, a_OrderType, a_OrderCond);
                            curTable.PendingOrderBuySell = a_BuySell;
                            curTable.PendingOrderVal = a_CurVal;
                            curTable.PendingOrderAmount = a_OrderAmount;
                            curTable.PendingOrder = true;
                            curTable.LiquidatingOrderNumber = orderNum;
                            string orderInfo = "청산 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_OldBuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                    }
                    else // 청산 가능 수량이 남아 있지 않을 때는 일반 주문으로 주문을 낸다.
                    {
                        object a_Market = "1";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = GetCurFutureCode();
                        object a_Amount = a_OrderAmount;
                        object a_OrderPrice = a_CurVal;
                        object a_OrderType = GlobalVar.OrderType;
                        object a_OrderCond = GlobalVar.OrderCond;
                        SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                        string orderInfo = "자동 일반 주문 정보 ->";
                        orderInfo += "주문계좌 : " + a_Account + ", ";
                        orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                        orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                        orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                        orderInfo += "주문수량 : " + a_Amount.ToString();
                        GlobalVar.WriteLog(orderInfo);
                    }
                }
                else // 이전 주문이 아예 없을 때는 최초 주문을 내보낸다.
                {
                    object a_Market = "1";
                    object a_Account = curTable.TableName;
                    object a_ItemCode = GetCurFutureCode();
                    object a_Amount = a_OrderAmount;
                    object a_OrderPrice = a_CurVal;
                    object a_OrderType = GlobalVar.OrderType;
                    object a_OrderCond = GlobalVar.OrderCond;
                    SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                    string orderInfo = "자동 최초 일반 주문 정보 ->";
                    orderInfo += "주문계좌 : " + a_Account + ", ";
                    orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                    orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                    orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                    orderInfo += "주문수량 : " + a_Amount.ToString();
                    GlobalVar.WriteLog(orderInfo);
                }
            }

            GlobalVar.DownloadLock = false;
        }


        // 옵션 주문 함수
        public void SendAutoLiquidAndOrder(int a_BuySell, int a_OrderAmount, double a_CurVal, string a_Code)
        {
            GlobalVar.DownloadLock = true;
            // 가장 먼저 청산 가능 수량이 있는지 조사한다.
            // 청산 가능 수량이 있으면 현재 주문 정보를 해당 계좌의 테이블에 저장해 둔다.
            // 그리고 청산 주문을 낸다. 해당 계좌의 테이블에 현재 청산 주문이 나갔음을 설정해 둔다.
            // 청산 주문이 완료 되면 원래 주문 정보를 가져와 본 주문을 넣어 준다.
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    DataRow lastRow = curTable.Rows[rowCount - 1];
                    int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                    string remainCode = lastRow["잔고구분코드"].ToString();
                    // 청산 가능 수량이 0보다 클 때
                    if (remainCode != "" && (remainCode == "1" || remainCode == "2") && liquidAmount > 0)
                    {
                        object a_Market = "2";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = a_Code;
                        object a_Amount = liquidAmount;
                        object a_OrderPrice = a_CurVal;
                        object a_OldBuySell;
                        object a_OrderType = 2;
                        object a_OrderCond = 0;
                        string orderNum = "";
                        // 매도 잔고가 남아 있는 상태임
                        if (remainCode == "1")
                        {
                            a_OldBuySell = GlobalVar.OrderBuy; // 매수 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            orderNum = SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_OldBuySell, a_OrderType, a_OrderCond);
                            curTable.PendingOrderBuySell = a_BuySell;
                            curTable.PendingOrderVal = a_CurVal;
                            curTable.PendingOrderAmount = a_OrderAmount;
                            curTable.PendingOrder = true;
                            curTable.LiquidatingOrderNumber = orderNum;
                            string orderInfo = "자동 청산 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_OldBuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                        else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                        {
                            // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                            a_OldBuySell = GlobalVar.OrderSell; // 매도 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            orderNum = SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_OldBuySell, a_OrderType, a_OrderCond);
                            curTable.PendingOrderBuySell = a_BuySell;
                            curTable.PendingOrderVal = a_CurVal;
                            curTable.PendingOrderAmount = a_OrderAmount;
                            curTable.PendingOrder = true;
                            curTable.LiquidatingOrderNumber = orderNum;
                            string orderInfo = "청산 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_OldBuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                    }
                    else // 청산 가능 수량이 남아 있지 않을 때는 일반 주문으로 주문을 낸다.
                    {
                        object a_Market = "1";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = GetCurFutureCode();
                        object a_Amount = a_OrderAmount;
                        object a_OrderPrice = a_CurVal;
                        object a_OrderType = GlobalVar.OrderType;
                        object a_OrderCond = GlobalVar.OrderCond;
                        SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                        string orderInfo = "자동 일반 주문 정보 ->";
                        orderInfo += "주문계좌 : " + a_Account + ", ";
                        orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                        orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                        orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                        orderInfo += "주문수량 : " + a_Amount.ToString();
                        GlobalVar.WriteLog(orderInfo);
                    }
                }
                else // 이전 주문이 아예 없을 때는 최초 주문을 내보낸다.
                {
                    object a_Market = "1";
                    object a_Account = curTable.TableName;
                    object a_ItemCode = GetCurFutureCode();
                    object a_Amount = a_OrderAmount;
                    object a_OrderPrice = a_CurVal;
                    object a_OrderType = GlobalVar.OrderType;
                    object a_OrderCond = GlobalVar.OrderCond;
                    SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                    string orderInfo = "자동 최초 일반 주문 정보 ->";
                    orderInfo += "주문계좌 : " + a_Account + ", ";
                    orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                    orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                    orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                    orderInfo += "주문수량 : " + a_Amount.ToString();
                    GlobalVar.WriteLog(orderInfo);
                }
            }

            GlobalVar.DownloadLock = false;
        }


        // 청산주문을 보낸다.
        public void SendLiquidOrder(int a_LiquidAmount, double a_CurVal)
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    DataRow lastRow = curTable.Rows[rowCount - 1];
                    int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                    // 요청한 청산 갯수가 남아 있는 청산 갯수보다 많으면 남아 있는 청산 갯수로 교체해 준다.
                    if (a_LiquidAmount > liquidAmount)
                        a_LiquidAmount = liquidAmount;

                    string remainCode = lastRow["잔고구분코드"].ToString();
                    // 청산 가능 수량이 0보다 클 때
                    if (remainCode != "" && (remainCode == "1" || remainCode == "2") && liquidAmount > 0)
                    {
                        object a_Market = "1";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = m_FCode.GetData(0, 0);
                        object a_Amount = a_LiquidAmount;
                        object a_OrderPrice = 0;
                        object a_BuySell = 0;
                        object a_OrderType = 2;
                        object a_OrderCond = 0;
                        // 매도 잔고가 남아 있는 상태임
                        if (remainCode == "1")
                        {
                            a_BuySell = 2; // 매수 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매수 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_CurVal.ToString("F2") + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                        else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                        {
                            // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                            a_BuySell = 1; // 매도 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매도 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_CurVal.ToString("F2") + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                    }
                }
            }

            GlobalVar.DownloadLock = false;
        }

        /*
        public void SendLiquidOrder(int a_LiquidAmount, double a_CurVal, string a_Code)
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    DataRow lastRow = curTable.Rows[rowCount - 1];
                    int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                    // 요청한 청산 갯수가 남아 있는 청산 갯수보다 많으면 남아 있는 청산 갯수로 교체해 준다.
                    if (a_LiquidAmount > liquidAmount)
                        a_LiquidAmount = liquidAmount;

                    string remainCode = lastRow["잔고구분코드"].ToString();
                    // 청산 가능 수량이 0보다 클 때
                    if (remainCode != "" && (remainCode == "1" || remainCode == "2") && liquidAmount > 0)
                    {
                        object a_Market = "1";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = a_Code;
                        object a_Amount = a_LiquidAmount;
                        object a_OrderPrice = 0;
                        object a_BuySell = 0;
                        object a_OrderType = 2;
                        object a_OrderCond = 0;
                        // 매도 잔고가 남아 있는 상태임
                        if (remainCode == "1")
                        {
                            a_BuySell = 2; // 매수 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매수 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_CurVal.ToString("F2") + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                        else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                        {
                            // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                            a_BuySell = 1; // 매도 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매도 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_CurVal.ToString("F2") + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                    }
                }
            }

            GlobalVar.DownloadLock = false;
        }
        */

        public void SendLiquidOrder(int a_LiquidAmount, double a_CurVal, string a_Code)
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    DataRow lastRow = curTable.Rows[rowCount - 1];
                    int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                    // 요청한 청산 갯수가 남아 있는 청산 갯수보다 많으면 남아 있는 청산 갯수로 교체해 준다.
                    if (a_LiquidAmount > liquidAmount)
                        a_LiquidAmount = liquidAmount;

                    string remainCode = lastRow["잔고구분코드"].ToString();
                    // 청산 가능 수량이 0보다 클 때
                    if (remainCode != "" && (remainCode == "1" || remainCode == "2") && liquidAmount > 0)
                    {
                        object a_Market = "1";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = a_Code;
                        object a_Amount = a_LiquidAmount;
                        object a_OrderPrice = 0;
                        object a_BuySell = 0;
                        object a_OrderType = 2;
                        object a_OrderCond = 0;
                        // 매도 잔고가 남아 있는 상태임
                        if (remainCode == "1")
                        {
                            a_BuySell = 2; // 매수 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매수 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_CurVal.ToString("F2") + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                        else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                        {
                            // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                            a_BuySell = 1; // 매도 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매도 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_CurVal.ToString("F2") + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                    }
                }
            }

            GlobalVar.DownloadLock = false;
        }


        // 매수 주문을 내보낸다.
        public void OrderBuy(double a_CurVal, int a_OrderAmount)
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                object a_Market = "1";
                object a_Account = curTable.TableName;
                object a_ItemCode = GetCurFutureCode();
                object a_Amount = a_OrderAmount;
                object a_OrderPrice = a_CurVal;
                object a_BuySell = 2;
                object a_OrderType = GlobalVar.OrderType;
                object a_OrderCond = GlobalVar.OrderCond;
                SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
            }

            GlobalVar.DownloadLock = false;
        }

        // 매수 주문을 내보낸다.
        public void SendAutoOrder(int buySell, double a_CurVal, int a_OrderAmount)
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                // 주문을 내기 전에 주문 중복 검사를 한다.
                // 자동 주문은 같은 종류의 주문을 내지 않는다.
                OrderInfo lastOrder = curTable.GetLastOrder();
                if (lastOrder != null)
                {
                    // 같은 종류의 주문은 받지 않는다.
                    if (lastOrder.Order == buySell)
                        continue;
                }

                if (buySell == GlobalVar.OrderBuy)
                {
                    GlobalVar.PlayOrderBuySound();
                }
                else if (buySell == GlobalVar.OrderSell)
                {
                    GlobalVar.PlayOrderSellSound();
                }


                object a_Market = "1";
                object a_Account = curTable.TableName;
                object a_ItemCode = GetCurFutureCode();
                object a_Amount = a_OrderAmount;
                object a_OrderPrice = a_CurVal;
                object a_BuySell = buySell;
                object a_OrderType = GlobalVar.OrderType;
                object a_OrderCond = GlobalVar.OrderCond;
                SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
            }

            GlobalVar.DownloadLock = false;
        }

        public bool SendAutoStop(double a_CurVal)
        {
            GlobalVar.DownloadLock = true;
            bool result = false;
            if (m_OrderDataSet == null)
                return result;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    double fixedProfit = 0;
                    double flowProfit = 0;
                    double totalProfit = curTable.CalcProfit(ref fixedProfit, ref flowProfit, a_CurVal);
                    // 정해진 이익 금액을 넘었거나 정해진 손실 금액을 넘었을 때 자동 청산한다.
                    if (GlobalVar.AutoProfitStopPrice != 0.0 && totalProfit >= GlobalVar.AutoProfitStopPrice)
                    {
                        Liquid(curTable);
                        result = true;
                        GlobalVar.WriteLog("이익에 의한 자동 청산 주문 나감.");
                    }

                    // 정해진 이익 금액을 넘었거나 정해진 손실 금액을 넘었을 때 자동 청산한다.
                    if (GlobalVar.AutoLossStopPrice != 0 && totalProfit <= -GlobalVar.AutoLossStopPrice)
                    {
                        Liquid(curTable);
                        result = true;
                        GlobalVar.WriteLog("손실에 의한 자동 청산 주문 나감.");
                    }
                }
            }

            GlobalVar.DownloadLock = false;
            return result;
        }

        public void SendAutoLiquid()
        {
            GlobalVar.WriteLog("자동청산 주문이 나감");
            GlobalVar.DownloadLock = true;
            LiquidAll();
            GlobalVar.DownloadLock = false;
        }

        public void SendAutoLiquid(string a_Code)
        {
            GlobalVar.WriteLog("자동청산 주문이 나감");
            GlobalVar.DownloadLock = true;
            LiquidAll(a_Code);
            GlobalVar.DownloadLock = false;
        }

        // 매도 주문을 내보낸다.
        public void OrderSell(double a_CurVal, int a_OrderAmount)
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                object a_Market = "1";
                object a_Account = curTable.TableName;
                object a_ItemCode = GetCurFutureCode();
                object a_Amount = a_OrderAmount;
                object a_OrderPrice = a_CurVal;
                object a_BuySell = 1;
                object a_OrderType = GlobalVar.OrderType;
                object a_OrderCond = GlobalVar.OrderCond;
                SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
            }

            GlobalVar.DownloadLock = false;
        }

        public void SetStopInfo(string a_AccountName, int a_StopOrderType, double a_StopVal)
        {
            if (m_OrderDataSet == null)
                return;
            OrderTable curTable = m_OrderDataSet.GetTable(a_AccountName);
            if (curTable == null)
                return;
            curTable.StopOrderType = a_StopOrderType;
            curTable.StopVal = a_StopVal;
            curTable.StopEnabled = true;
        }

        public void ClearStopInfo(string a_AccountName)
        {
            if (m_OrderDataSet == null)
                return;
            OrderTable curTable = m_OrderDataSet.GetTable(a_AccountName);
            if (curTable == null)
                return;
            curTable.StopOrderType = 0;
            curTable.StopVal = 0;
            curTable.StopEnabled = false;
        }

        private OrderFrm m_OrderFrame = null;
        public EasyTrader.Order.OrderFrm OrderFrame
        {
            get { return m_OrderFrame; }
            set { m_OrderFrame = value; }
        }

        public void SaveOrderTables()
        {
            if (m_OrderDataSet == null)
                return;
            m_OrderDataSet.SaveTablesToXML();
        }
        private EasyTrader.Order.ETOrderDataSet m_OrderDataSet = new EasyTrader.Order.ETOrderDataSet("EasyTraderOrderDataSet");
        public EasyTrader.Order.ETOrderDataSet OrderDataSet
        {
            get { return m_OrderDataSet; }
            set { m_OrderDataSet = value; }
        }
       
        // 참조할 테이블
        private FutureJpBidTable m_ObjectFutureJpBidTable = null;
        public EasyTrader.FutureJpBidTable ObjectFutureJpBidTable
        {
            get { return m_ObjectFutureJpBidTable; }
            set { m_ObjectFutureJpBidTable = value; }
        }
        // 계좌 번호 배열
        private Array m_arAccount;
        public Array GetAccountArray()
        {
            return m_arAccount;
        }
        // 체결 정보
        private DSCBO1Lib.CpFConclusionClass m_CpFConclusion = new DSCBO1Lib.CpFConclusionClass();
        public DSCBO1Lib.CpFConclusionClass CpFConclusion
        {
            get { return m_CpFConclusion; }
            set { m_CpFConclusion = value; }
        }
        // 주문 유틸
        private CPTRADELib.CpTdUtilClass m_TdUtil = new CPTRADELib.CpTdUtilClass();
        public CPTRADELib.CpTdUtilClass TdUtil
        {
            get { return m_TdUtil; }
            set { m_TdUtil = value; }
        }
        // 주문 객체 
        private CPTRADELib.CpTd6831Class m_Cp6831 = new CPTRADELib.CpTd6831Class();
        public CPTRADELib.CpTd6831Class Cp6831
        {
            get { return m_Cp6831; }
            set { m_Cp6831 = value; }
        }
        // 수정 객체
        private CPTRADELib.CpTd6831Class m_Cp6832 = new CPTRADELib.CpTd6831Class();
        public CPTRADELib.CpTd6831Class Cp6832
        {
            get { return m_Cp6832; }
            set { m_Cp6832 = value; }
        }
        // 취소 객체
        private CPTRADELib.CpTd6831Class m_Cp6833 = new CPTRADELib.CpTd6831Class();
        public CPTRADELib.CpTd6831Class Cp6833
        {
            get { return m_Cp6833; }
            set { m_Cp6833 = value; }
        }
        // 종목 코드 객체
        private CPUTILLib.CpFutureCode m_FCode = new CPUTILLib.CpFutureCode();
        // 당일 매매 손익 조회 객체
        private CPTRADELib.CpTd6197Class m_Cp6197 = new CPTRADELib.CpTd6197Class();
        public CPTRADELib.CpTd6197Class Cp6197
        {
            get { return m_Cp6197; }
            set { m_Cp6197 = value; }
        }

        // 당일 매매 손익 조회 객체
        private CPTRADELib.CpTd0723Class m_CpTd0723 = new CPTRADELib.CpTd0723Class();
        public CPTRADELib.CpTd0723Class CpTd0723
        {
            get { return m_CpTd0723; }
            set { m_CpTd0723 = value; }
        }
        // 주문 초기화 변수 - 이 변수가 참일 때만 주문이 진행된다.
        private bool m_OrderInitialized = false;
        public bool OrderInitialized
        {
            get { return m_OrderInitialized; }
            set { m_OrderInitialized = value; }
        }
        // 정상 주문을 보낸다.
        public string SendNormalOrder(object a_Market, object a_Account, object a_ItemCode, object a_Amount, object a_OrderPrice, object a_BuySell, object a_OrderType, object a_OrderCond)
        {
            GlobalVar.DownloadLock = true;
            GlobalVar.WriteLog("PutOrderBegin");
            //주문 설정
            //m_Cp6831.SetInputValue(0, a_Market); // 선물/옵션 구분 ("1":선물, "2":옵션, "3":개별주식옵션...)            
            m_Cp6831.SetInputValue(1, a_Account); // 계좌번호
            m_Cp6831.SetInputValue(2, a_ItemCode); // 종목코드
            m_Cp6831.SetInputValue(3, a_Amount); // 주문수량
            m_Cp6831.SetInputValue(4, a_OrderPrice); // 주문 가격 - 시장가인 경우는 0으로 설정한다.
            m_Cp6831.SetInputValue(5, a_BuySell); // 매수
            // 여기서는 무조건 시장가로 주문을 한다.
            m_Cp6831.SetInputValue(6, a_OrderType); // 시장가
            m_Cp6831.SetInputValue(7, a_OrderCond); // 주문 조건 코드 0:없음, 1:IOC, 2:FOK
            int nRet = 0;
            try
            {
                // 데이터 수신 요청을 한다.
                nRet = m_Cp6831.BlockRequest();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            String returnStr = String.Format("{0:0,0}", nRet);
            Console.WriteLine(m_Cp6831.GetDibMsg1());
            GlobalVar.WriteLog(returnStr);

            returnStr += m_Cp6831.GetDibMsg1();

            GlobalVar.ServerOrderMsg = returnStr;

            /*
             * 리턴값
            0: 정상요청
            1: 통신요청 실패
            2: 주문확인창에서 취소
            3: 그외의 내부 오류
            4: 주문요청 제한 개수 초과
            */
            // 반환값이 0이 아니면 오류가 발생한 것이다.
            if (nRet != 0)
            {
                return "";
            }

            object orderNum = m_Cp6831.GetHeaderValue(8);
            Console.WriteLine(orderNum.ToString());
            // 여기까지 왔으면 서버에서 정보가 온것이다.
            // 여기서 주문 정보를 생성하고 저장해 준다.
            OrderTable curTable = m_OrderDataSet.GetTable(a_Account.ToString());
            if (curTable != null)
            {
                // 21 개 항목
                object[] orderInfo = new object[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
                orderInfo[0] = 0;
                orderInfo[1] = GlobalVar.DayIndex(); // index
                orderInfo[2] = GlobalVar.TimeToIntEx(); // 시분초
                orderInfo[3] = m_Cp6831.GetHeaderValue(13); // 종목코드
                orderInfo[4] = a_Amount; // 주문수량
                orderInfo[5] = a_OrderPrice; // 주문가격
                orderInfo[6] = a_BuySell; // 주문구분 매수(2), 매도(1)
                orderInfo[7] = a_OrderType; // 매매구분 : 지정가(1), 시장가(2), 조건부지정가(3), 최유리지정가(4)
                orderInfo[8] = a_OrderCond; // 주문조건 : 없음(0), IOC(1), FOK(2)
                orderInfo[9] = m_Cp6831.GetHeaderValue(1); // 계좌명
                orderInfo[10] = m_Cp6831.GetHeaderValue(2); // 종목명
                orderInfo[11] = m_Cp6831.GetHeaderValue(8); // 주문번호
                orderInfo[18] = 100; // 100은 주문 요청이다.
                // 주문정보를 테이블에 넣어 준다.
                curTable.AddRow(orderInfo);

                // 여기서 주문 창을 갱신해 준다.
                if (m_OrderFrame != null)
                {
                    m_OrderFrame.ShowOrderPrice(a_Account);
                }
                GlobalVar.OrderState = "주문요청";
                if (m_OrderFrame != null)
                {
                    m_OrderFrame.ShowOrderState(curTable);
                }
            }

            GlobalVar.DownloadLock = false;
            return orderNum.ToString();
        }

        // 정정 주문을 보낸다.
        public string SendModifyOrder(object a_Account, object a_OriginOrderNumber, object a_ItemCode, object a_Amount, object a_OrderPrice, object a_OrderType, object a_OrderCond)
        {
            GlobalVar.DownloadLock = true;
            GlobalVar.WriteLog("SendModifyOrder");

            if (m_OrderDataSet == null || m_CpFConclusion == null)
                return "";

            // 계좌번호로 테이블을 가져온다.
            OrderTable curTable = m_OrderDataSet.GetTable(a_Account.ToString());
            if (curTable == null)
                return "";

            // 원주문번호와 일치하는 열을 찾는다.
            DataRow curRow = curTable.GetRowByOrderNumber(a_OriginOrderNumber.ToString());
            if (curRow["주문구분"] == DBNull.Value)
                return "";

            //주문 설정
            //m_Cp6832.SetInputValue(0, a_Market); // 선물/옵션 구분 ("1":선물, "2":옵션, "3":개별주식옵션...)            
            m_Cp6832.SetInputValue(2, a_OriginOrderNumber); // 원주문번호
            m_Cp6832.SetInputValue(3, a_Account); // 계좌번호
            m_Cp6832.SetInputValue(4, a_ItemCode); // 종목코드
            m_Cp6832.SetInputValue(5, a_Amount); // 주문수량
            m_Cp6832.SetInputValue(6, a_OrderPrice); // 주문 가격 - 시장가인 경우는 0으로 설정한다.
            // 여기서는 무조건 시장가로 주문을 한다.
            m_Cp6832.SetInputValue(8, a_OrderType); // 시장가
            m_Cp6832.SetInputValue(9, a_OrderCond); // 주문 조건 코드 0:없음, 1:IOC, 2:FOK
            int nRet = 0;
            try
            {
                // 데이터 수신 요청을 한다.
                m_Cp6832.Request();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            String returnStr = String.Format("{0:0,0}", nRet);
            Console.WriteLine(m_Cp6832.GetDibMsg1());
            GlobalVar.WriteLog(returnStr);

            /*
             * 리턴값
            0: 정상요청
            1: 통신요청 실패
            2: 주문확인창에서 취소
            3: 그외의 내부 오류
            4: 주문요청 제한 개수 초과
            */
            // 반환값이 0이 아니면 오류가 발생한 것이다.
            if (nRet != 0)
            {
                return "";
            }

            object orderNum = m_Cp6832.GetHeaderValue(8);
            Console.WriteLine(orderNum.ToString());
            // 여기까지 왔으면 서버에서 정보가 온것이다.
            // 여기서 주문 정보를 생성하고 저장해 준다.
            if (curTable != null)
            {
                // 21 개 항목
                object[] orderInfo = new object[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                orderInfo[0] = 1;
                orderInfo[1] = GlobalVar.DayIndex(); // index
                orderInfo[2] = GlobalVar.TimeToIntEx(); // 시분초
                orderInfo[3] = m_Cp6832.GetHeaderValue(12); // 종목코드
                orderInfo[4] = a_Amount; // 주문수량
                orderInfo[5] = a_OrderPrice; // 주문가격
                orderInfo[6] = curRow["주문구분"];
                orderInfo[7] = a_OrderType; // 매매구분 : 지정가(1), 시장가(2), 조건부지정가(3), 최유리지정가(4)
                orderInfo[8] = a_OrderCond; // 주문조건 : 없음(0), IOC(1), FOK(2)
                orderInfo[9] = m_Cp6832.GetHeaderValue(2); // 계좌명
                orderInfo[10] = m_Cp6832.GetHeaderValue(3); // 종목명
                orderInfo[11] = m_Cp6832.GetHeaderValue(6); // 주문번호 // 원주문번호 외에 새로 받은 주문번호임.
                orderInfo[18] = 100; // 100은 주문 요청이다.
                // 주문정보를 테이블에 넣어 준다.
                curTable.AddRow(orderInfo);
                GlobalVar.OrderState = "수정요청";
                if (m_OrderFrame != null)
                {
                    m_OrderFrame.ShowOrderState(curTable);
                }
            }
            GlobalVar.DownloadLock = false;
            return orderNum.ToString();
        }

        // 최근월물 선물 코드를 가져 온다.
        public string GetCurFutureCode()
        {
            string futureCode = "";
            if (m_FCode == null)
                return futureCode;

            futureCode = m_FCode.GetData(0, 0).ToString();

            return futureCode;
        }
        // 취소 주문을 보낸다.
        public string SendCancelOrder(object a_Account, object a_OriginOrderNumber, object a_ItemCode, object a_Amount)
        {
            GlobalVar.DownloadLock = true;
            GlobalVar.WriteLog("SendCancelOrder");

            if (m_OrderDataSet == null || m_CpFConclusion == null)
                return "";

            // 계좌번호로 테이블을 가져온다.
            OrderTable curTable = m_OrderDataSet.GetTable(a_Account.ToString());
            if (curTable == null)
                return "";

            // 원주문번호와 일치하는 열을 찾는다.
            DataRow curRow = curTable.GetRowByOrderNumber(a_OriginOrderNumber.ToString());
            if (curRow["주문구분"] == DBNull.Value)
                return "";

            //주문 설정
            m_Cp6833.SetInputValue(2, a_OriginOrderNumber); // 원주문번호
            m_Cp6833.SetInputValue(3, a_Account); // 계좌번호
            m_Cp6833.SetInputValue(4, a_ItemCode); // 종목코드
            m_Cp6833.SetInputValue(5, a_Amount); // 취소수량
            int nRet = 0;
            try
            {
                // 데이터 수신 요청을 한다.
                m_Cp6833.Request();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            String returnStr = String.Format("{0:0,0}", nRet);
            Console.WriteLine(m_Cp6832.GetDibMsg1());
            GlobalVar.WriteLog(returnStr);

            /*
             * 리턴값
            0: 정상요청
            1: 통신요청 실패
            2: 주문확인창에서 취소
            3: 그외의 내부 오류
            4: 주문요청 제한 개수 초과
            */
            // 반환값이 0이 아니면 오류가 발생한 것이다.
            if (nRet != 0)
            {
                return "";
            }

            object orderNum = m_Cp6833.GetHeaderValue(8);
            Console.WriteLine(orderNum.ToString());
            // 여기까지 왔으면 서버에서 정보가 온것이다.
            // 여기서 주문 정보를 생성하고 저장해 준다.
            if (curTable != null)
            {
                // 21 개 항목
                object[] orderInfo = new object[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                orderInfo[0] = 2;
                orderInfo[1] = GlobalVar.DayIndex(); // index
                orderInfo[2] = GlobalVar.TimeToIntEx(); // 시분초
                orderInfo[3] = m_Cp6833.GetHeaderValue(12); // 종목코드
                orderInfo[4] = a_Amount; // 주문수량
                orderInfo[6] = curRow["주문구분"];
                orderInfo[9] = m_Cp6833.GetHeaderValue(2); // 계좌명
                orderInfo[10] = m_Cp6833.GetHeaderValue(3); // 종목명
                orderInfo[11] = m_Cp6833.GetHeaderValue(6); // 주문번호 // 원주문번호 외에 새로 받은 주문번호임.
                orderInfo[18] = 100; // 100은 주문 요청이다.
                // 주문정보를 테이블에 넣어 준다.
                curTable.AddRow(orderInfo);
                GlobalVar.OrderState = "취소요청";
                if (m_OrderFrame != null)
                {
                    m_OrderFrame.ShowOrderState(curTable);
                }
            }

            GlobalVar.DownloadLock = false;
            return orderNum.ToString();
        }

        public string GetAccountNum(int a_Index)
        {
            string accountNum = "";
            if (m_OrderDataSet == null)
                return accountNum;
            accountNum = m_OrderDataSet.GetTableName(a_Index);
            return accountNum;
        }
        // 주문을 위해 초기화 한다.
        public void InitOrder()
        {
            if (m_OrderInitialized == true)
                return;

            //주문 초기화
            int nRet;
            do
            {
                nRet = m_TdUtil.TradeInit(0);
            } while (nRet != 0);

            //주문이벤트등록
            m_CpFConclusion.Received += new DSCBO1Lib._IDibEvents_ReceivedEventHandler(CpFConclusion_OnReceived);
            m_CpFConclusion.Subscribe();

            //ReadAccountInfo();
            //계좌번호 얻기                        
            GlobalVar.WriteLog(m_TdUtil.AccountNumber.ToString());
            m_arAccount = (Array)m_TdUtil.AccountNumber;
            GlobalVar.WriteLog(m_arAccount.GetValue(0).ToString());
            for (int i = 0; i < m_arAccount.GetLength(0); i++)
            {
                // 계좌번호로 테이블을 만든다.
                string accountNumber = m_arAccount.GetValue(i).ToString();
                if (m_OrderDataSet != null)
                {
                    m_OrderDataSet.CreateOrderTable(accountNumber);
                }
            }

            GlobalVar.WriteLog("계좌 가져옴");
            //최근월물의 현재가격으로 선물주문 요청
            OrderInitialized = true;
            GlobalVar.WriteLog("계좌 가져오기 완료");

        }

        private void AddSignal(OrderTable a_Table, object a_OrderType, object a_OrderPrice)
        {
            if (a_Table == null)
                return;

            int dayIndex = GlobalVar.DayIndex();
            int curTime = GlobalVar.TimeToIntEx();
            EasyTrader.Signal.PriceSignal signal = new EasyTrader.Signal.PriceSignal();
            signal.X = dayIndex;
            signal.Y = Convert.ToDouble(a_OrderPrice);
            signal.Type = Convert.ToInt32(a_OrderType);
            signal.Time = curTime;
            a_Table.AddSignal(signal);
        }
        
        // 주문 체결 정보를 처리함
        public void CpFConclusion_OnReceived()
        {
            if (m_OrderDataSet == null || m_CpFConclusion == null)
                return;

            // 계좌번호를 가져온다.
            object accountNumber = m_CpFConclusion.GetHeaderValue(7);
            // 계좌번호로 테이블을 가져온다.
            OrderTable curTable = m_OrderDataSet.GetTable(accountNumber.ToString());
            if (curTable == null)
                return;

            // 주문번호를 가져온다.
            object orderNumber = m_CpFConclusion.GetHeaderValue(5);
            // 주문번호와 일치하는 열을 찾는다. 주문번호는 수정이나 취소에서도 새롭게 주어진다.
            DataRow curRow = curTable.GetRowByOrderNumber(orderNumber.ToString());
            if (curRow != null)
            {
                curRow["원주문번호"] = m_CpFConclusion.GetHeaderValue(6);
                curRow["종합계좌번호"] = m_CpFConclusion.GetHeaderValue(7);
                curRow["거래명칭"] = m_CpFConclusion.GetHeaderValue(0);
                curRow["체결수량"] = m_CpFConclusion.GetHeaderValue(3);
                curRow["체결가격"] = m_CpFConclusion.GetHeaderValue(4);
                curRow["체결시각"] = GlobalVar.TimeToIntEx();
                curRow["주문상태"] = m_CpFConclusion.GetHeaderValue(44);
                curRow["잔고구분코드"] = m_CpFConclusion.GetHeaderValue(45);
                curRow["잔고"] = m_CpFConclusion.GetHeaderValue(46);
                curRow["청산가능수량"] = m_CpFConclusion.GetHeaderValue(47);
            }

            object originOrderNumber = m_CpFConclusion.GetHeaderValue(6);

            int orderState = Convert.ToInt32(m_CpFConclusion.GetHeaderValue(44));
            // 체결 완료상태에서 기준의 주문 정보를 갱신시켜 준다.
            if (orderState == 4)
            {
                //UpdateRemainInfo(curTable);
                //object orderType = m_CpFConclusion.GetHeaderValue(12);
                //object orderPrice = m_CpFConclusion.GetHeaderValue(4);
                //AddSignal(curTable, orderType, orderPrice);
                // 현재 처리되지 않은 주문이 있다면 추가로 주문을 넣어 준다.
                SendPendingOrder(curTable, orderNumber.ToString());
            }

            // 여기서 주문 창을 갱신해 준다.
            if (m_OrderFrame != null)
            {
                // 주문 테이블에 근거하여 필수 정보로 주문목록을 만든다.
                //MakeOrderList(curTable);
                m_OrderFrame.ShowOrderPrice(accountNumber);
                // 현재 수익을 계산해 준다.
                double fixedProfit = 0;
                double flowProfit = 0;
                curTable.CalcProfit(ref fixedProfit, ref flowProfit, GlobalVar.CurClose);
            }

            if (orderState == 1)
                GlobalVar.OrderState = "(주문접수완료)";
            else if (orderState == 2)
                GlobalVar.OrderState = "(정정확인)";
            else if (orderState == 3)
                GlobalVar.OrderState = "(취소확인)";
            else if (orderState == 4)
                GlobalVar.OrderState = "(주문체결완료)";
            else if (orderState == 5)
                GlobalVar.OrderState = "(주문거부)";
            else
                GlobalVar.OrderState = "(알수없음)";

            if (m_OrderFrame != null)
            {
                m_OrderFrame.ShowOrderState(curTable);
            }

            curTable.MakeOrderList();
        }

        // 이 함수는 체결이 완료되었을 때 잔고 내용을 갱신해 준다.
        private void UpdateRemainInfo(OrderTable a_OrderTable)
        {
            if (a_OrderTable == null)
                return;

            int rowCount = a_OrderTable.Rows.Count;
            if (rowCount <= 1)
                return;

            DataRow curRow = a_OrderTable.Rows[rowCount - 1];
            object lasrRemainCode = curRow["잔고구분코드"];
            object lastRemain = curRow["잔고"];
            object lastLiquidAmount = curRow["청산가능수량"];

            for (int i = 1; i < rowCount; i++)
            {
                curRow = a_OrderTable.Rows[i];
                curRow["잔고구분코드"] = lasrRemainCode;
                curRow["잔고"] = lastRemain;
                curRow["청산가능수량"] = lastLiquidAmount;
            }
        }

        public void GetAccountBalance(object a_AccountNumber)
        {
            m_CpTd0723.SetInputValue(0, a_AccountNumber);
            DateTime now;
            now = DateTime.Now;

            string curDate = now.Year.ToString();
            if (now.Month < 10)
                curDate += ("0" + now.Month.ToString());
            else
                curDate += now.Month.ToString();
            if (now.Day < 10)
            {
                curDate += ("0" + now.Day.ToString());
            }
            else
            {
                curDate += now.Day.ToString();
            }
            object date = curDate;
            //m_Cp6197.SetInputValue(1, date);
            //m_Cp6197.SetInputValue(2, "50");
            //m_Cp6197.SetInputValue(3, 10);

            int ret = 0;
            try
            {
                // 데이터 수신 요청을 한다.
                ret = m_CpTd0723.BlockRequest();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            int dataCount = Convert.ToInt32(m_CpTd0723.GetHeaderValue(2));
            for (int j = 0; j < dataCount; j++)
            {
                // 계좌 번호
                object AccountNumber = m_CpTd0723.GetDataValue(0, j);
                // 예탁 현금
                object DepositMoney = m_CpTd0723.GetDataValue(1, j);
                // 익일 가예탁 현금
                object NextDayDepositMoney = m_CpTd0723.GetDataValue(2, j);
                // 전일 잔고 손익합
                object PreDayBalance = Convert.ToInt32(m_CpTd0723.GetDataValue(3, j));
                // 금일 매매 손익합
                object TodayBalance = Convert.ToDouble(m_CpTd0723.GetDataValue(5, j));
                // 금일 매매 청산 손익합
                object TodayLiquidationBalance = Convert.ToInt32(m_CpTd0723.GetDataValue(9, j));
                // 총 손익합
                object TotalBalance = Convert.ToInt32(m_CpTd0723.GetDataValue(10, j));
            }
        }

        // 이 함수는 현재 계좌의 주문을 청산한다.
        public void Liquid(string a_AccountName)
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;
            
            OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[a_AccountName];
            if (curTable == null)
                return;

            int rowCount = curTable.Rows.Count;
            if (rowCount > 0)
            {
                DataRow lastRow = curTable.Rows[rowCount - 1];
                int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                string remainCode = lastRow["잔고구분코드"].ToString();
                // 청산 가능 수량이 0보다 클 때
                if (remainCode != "" && (remainCode == "1" || remainCode == "2") && liquidAmount > 0)
                {
                    object a_Market = "1";
                    object a_Account = curTable.TableName;
                    object a_ItemCode = m_FCode.GetData(0, 0);
                    object a_Amount = liquidAmount;
                    object a_OrderPrice = 0;
                    object a_BuySell;
                    object a_OrderType = 2;
                    object a_OrderCond = 0;
                    // 매도 잔고가 남아 있는 상태임
                    if (remainCode == "1")
                    {
                        a_BuySell = 2; // 매수 주문
                        // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                        SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                    }
                    else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                    {
                        // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                        a_BuySell = 1; // 매도 주문
                        // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                        SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                    }
                }
            }
            GlobalVar.DownloadLock = false;
        }

        public void Liquid(OrderTable curTable)
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;

            if (curTable == null)
                return;

            int rowCount = curTable.Rows.Count;
            if (rowCount > 0)
            {
                DataRow lastRow = curTable.Rows[rowCount - 1];
                int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                string remainCode = lastRow["잔고구분코드"].ToString();
                // 청산 가능 수량이 0보다 클 때
                if (remainCode != "" && (remainCode == "1" || remainCode == "2") && liquidAmount > 0)
                {
                    object a_Market = "1";
                    object a_Account = curTable.TableName;
                    object a_ItemCode = m_FCode.GetData(0, 0);
                    object a_Amount = liquidAmount;
                    object a_OrderPrice = 0;
                    object a_BuySell;
                    object a_OrderType = 2;
                    object a_OrderCond = 0;
                    // 매도 잔고가 남아 있는 상태임
                    if (remainCode == "1")
                    {
                        a_BuySell = 2; // 매수 주문
                        // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                        SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                    }
                    else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                    {
                        // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                        a_BuySell = 1; // 매도 주문
                        // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                        SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                    }
                }
            }
            GlobalVar.DownloadLock = false;
        }

        public void LiquidAll(string a_Code)
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for (int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    DataRow lastRow = curTable.Rows[rowCount - 1];
                    int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                    string remainCode = lastRow["잔고구분코드"].ToString();
                    // 청산 가능 수량이 0보다 클 때
                    if (remainCode != "" && (remainCode == "1" || remainCode == "2") && liquidAmount > 0)
                    {
                        object a_Market = "1";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = m_FCode.GetData(0, 0);
                        object a_Amount = liquidAmount;
                        object a_OrderPrice = 0;
                        object a_BuySell;
                        object a_OrderType = 2;
                        object a_OrderCond = 0;
                        // 매도 잔고가 남아 있는 상태임
                        if (remainCode == "1")
                        {
                            a_BuySell = 2; // 매수 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매수 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                        else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                        {
                            // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                            a_BuySell = 1; // 매도 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매도 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                    }
                }
            }

            GlobalVar.DownloadLock = false;
        }

        // 이 함수는 현재 모든 계좌의 주문을 청산한다.
        public void LiquidAll()
        {
            GlobalVar.DownloadLock = true;
            if (m_OrderDataSet == null)
                return;

            int tableCount = m_OrderDataSet.Tables.Count;
            for(int i = 0; i < tableCount; i++)
            {
                OrderTable curTable = (OrderTable)m_OrderDataSet.Tables[i];
                int rowCount = curTable.Rows.Count;
                if (rowCount > 0)
                {
                    DataRow lastRow = curTable.Rows[rowCount - 1];
                    int liquidAmount = Convert.ToInt32(lastRow["청산가능수량"]);
                    string remainCode = lastRow["잔고구분코드"].ToString();
                    // 청산 가능 수량이 0보다 클 때
                    if (remainCode != "" && (remainCode == "1" || remainCode == "2") &&liquidAmount > 0)
                    {
                        object a_Market = "1";
                        object a_Account = curTable.TableName;
                        object a_ItemCode = m_FCode.GetData(0,0);
                        object a_Amount = liquidAmount;
                        object a_OrderPrice = 0;
                        object a_BuySell;
                        object a_OrderType = 2;
                        object a_OrderCond = 0;
                        // 매도 잔고가 남아 있는 상태임
                        if (remainCode == "1")
                        {
                            a_BuySell = 2; // 매수 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매수 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                        else if (remainCode == "2") // 매수 잔고가 남아 있는 상태임
                        {
                            // 청산 가능 수량만큼 매도 주문으로 청산을 함.
                            a_BuySell = 1; // 매도 주문
                            // 청산 가능 수량만큼 매수 주문으로 청산을 함.
                            SendNormalOrder(a_Market, a_Account, a_ItemCode, a_Amount, a_OrderPrice, a_BuySell, a_OrderType, a_OrderCond);
                            string orderInfo = "모두 청산에서 매도 주문 정보 ->";
                            orderInfo += "주문계좌 : " + a_Account + ", ";
                            orderInfo += "주문시간 : " + GlobalVar.TimeToInt().ToString() + ", ";
                            orderInfo += "주문유형 : " + a_BuySell.ToString() + ", ";
                            orderInfo += "주문가격 : " + a_OrderPrice.ToString() + ", ";
                            orderInfo += "주문수량 : " + a_Amount.ToString();
                            GlobalVar.WriteLog(orderInfo);
                        }
                    }
                }
            }

            GlobalVar.DownloadLock = false;
        }
    }
}
